// this header is intended for use with standard integers
// byte-aligned, 8, 16, 32 (and probably 64) bits integers

#ifndef INT_HEADER
#define INT_HEADER

// this header needs
#include <stdio.h>
#include "BITS.h"
#include "../ARRAY.h"

// functions to print bean default integers
umax print_byte_num(void * ptr, umax size); // byte dec
umax print_byte_hex(void * ptr, umax size); // byte hex
umax print_char_t_num(void * ptr, umax size);
umax print_umax_num(void * ptr, umax size); // umax dec
umax print_umax_hex(void * ptr, umax size); // umax hex
umax print_smax_num(void * ptr, umax size);

// the below functions are functions to calculate, from bits, an integer.
// it does not assume that the system integer representation is the same
// as the integer that it is going to be read from memory. That is why some
// math is to be done

// basic functions for integers
umax powerof_uint(umax base, byte exponent);
smax powerof_sint(smax base, byte exponent);
umax get_max_uint(umax uint1, umax uint2);
umax get_min_uint(umax uint1, umax uint2);

// calculate specific types of integers from binary digits
// (from bits stored in BIT_HOLDER)

// UNSIGNED
umax bits_to_std_uint(umax bit_holder_pos);
// SIGNED
smax bits_to_sign_magnitude_sint(umax bit_holder_pos);
smax bits_to_1_complement_sint(umax bit_holder_pos);
smax bits_to_2_complement_sint(umax bit_holder_pos);
smax bits_to_offset_binary_sint(umax bit_holder_pos);
smax bits_to_base_minus2_sint(umax bit_holder_pos);

// get std/non-std unsigned/signed integers from memory (size in 
// bits, aligned to the leftmost byte from src by l_bit_pos)

// UNSIGNED
umax calc_mem_std_uint(umax byte_cnt, umax lshifts, umax bit_cnt, umax lpad_cnt, void * src, ENDIAN_T endian);
// SIGNED
// See https://en.wikipedia.org/wiki/Signed_number_representations
smax calc_mem_sign_mag_sint(umax byte_cnt, umax lshifts, umax bit_cnt, umax lpad_cnt, void * src, ENDIAN_T endian);
smax calc_mem_1_compl_sint(umax byte_cnt, umax lshifts, umax bit_cnt, umax lpad_cnt, void * src, ENDIAN_T endian);
smax calc_mem_2_compl_sint(umax byte_cnt, umax lshifts, umax bit_cnt, umax lpad_cnt, void * src, ENDIAN_T endian);
smax calc_mem_off_bin_sint(umax byte_cnt, umax lshifts, umax bit_cnt, umax lpad_cnt, void * src, ENDIAN_T endian);
smax calc_mem_bminus2_sint(umax byte_cnt, umax lshifts, umax bit_cnt, umax lpad_cnt, void * src, ENDIAN_T endian);

// the functions below assume that the bits from integers in memory
// follow the usual integer representation (2-complement for signed
// and normal unsigned representation) and that the system uses the
// same usual integer representation as well. Seems like a dumb thing
// to assume, as it is going to be like that on most systems as of
// today, but I do it to make this personal library as general as 
// possible for my future projects). Might be a lot of a struggle
// for such a small project but I'll still do it

// get std unsigned/signed integers from memory
umax get_uint(umax byte_cnt, umax lshifts, umax bit_cnt, umax lpad_cnt, void * src, ENDIAN_T endian);
smax get_sint(umax byte_cnt, umax lshifts, umax bit_cnt, umax lpad_cnt, void * src, ENDIAN_T endian);

// the functions below will work to get/write standard integers
// byte aligned and 8, 16 and 32 bits long signed/unsigned integers

// get std signed/unsigned integer from memory
umax get_std_uint(umax bit_cnt, void * src, ENDIAN_T endian);
smax get_std_sint(umax bit_cnt, void * src, ENDIAN_T endian);

// functions to print std integers
umax print_uint8(void * ptr, umax size); 
umax print_uint16be(void * ptr, umax size); 
umax print_uint16le(void * ptr, umax size); 
umax print_uint32be(void * ptr, umax size); 
umax print_uint32le(void * ptr, umax size);
umax print_sint8(void * ptr, umax size); 
umax print_sint16be(void * ptr, umax size); 
umax print_sint16le(void * ptr, umax size); 
umax print_sint32be(void * ptr, umax size); 
umax print_sint32le(void * ptr, umax size);  

// comparison functions
bool umax_equal(void * umax1, void * umax2);

// TODO

// print functions for the list adt
//~ void print_uint8(void * ptr);
//~ void print_uint16(void * ptr);
//~ void print_uint32(void * ptr);
//~ void print_sint8(void * ptr);
//~ void print_sint16(void * ptr);
//~ void print_sint32(void * ptr);

// compare functions, for sort_array()
//~ bool comp_uint8(void * ptr1, void * ptr2);
//~ bool comp_uint16(void * ptr1, void * ptr2);
//~ bool comp_uint32(void * ptr1, void * ptr2);
//~ bool comp_sint8(void * ptr1, void * ptr2);
//~ bool comp_sint16(void * ptr1, void * ptr2);
//~ bool comp_sint32(void * ptr1, void * ptr2);

#include "INT.c"

#endif // INT_HEADER
